
#include "string.h"
#include "sw_pwm.h"


void sw_pwm_set_compare_1(SW_PWM_STRUCT* sw_pwm, uint16_t compare_1)
{
    sw_pwm->compare_1 = compare_1;
}

void sw_pwm_set_compare_2(SW_PWM_STRUCT* sw_pwm, uint16_t compare_2)
{
    sw_pwm->compare_2 = compare_2;
}

void sw_pwm_set_idle_level(SW_PWM_STRUCT* sw_pwm, uint8_t idle_level)
{
    sw_pwm->state.idle_level = idle_level;
}

void sw_pwm_set_period(SW_PWM_STRUCT* sw_pwm, uint16_t period)
{
    sw_timer_set_period(&(sw_pwm->sw_timer), period);
}

uint16_t sw_pwm_get_period(SW_PWM_STRUCT* sw_pwm)
{
    return sw_timer_get_period(&(sw_pwm->sw_timer));
}

void sw_pwm_reset_counter(SW_PWM_STRUCT* sw_pwm)
{
    sw_timer_reset_counter(&(sw_pwm->sw_timer));
}

void sw_pwm_enable(SW_PWM_STRUCT* sw_pwm)
{
    sw_timer_enable(&(sw_pwm->sw_timer));
/**********************************************
	sw_pwm->state.current_level = sw_pwm->state.idle_level;
	if(sw_pwm->state.idle_level){
		if(sw_pwm->set_high_callback){
			sw_pwm->set_high_callback();
		}
	}
	else{
		if(sw_pwm->set_low_callback){
			sw_pwm->set_low_callback();
		}
	}
**********************************************/
}

void sw_pwm_disable(SW_PWM_STRUCT* sw_pwm)
{
    sw_timer_disable(&(sw_pwm->sw_timer));
}

uint8_t sw_pwm_check_enable(SW_PWM_STRUCT* sw_pwm)
{
    return sw_timer_check_enable(&(sw_pwm->sw_timer));
}

void sw_pwm_reset_timeout(SW_PWM_STRUCT* sw_pwm)
{
    sw_timer_reset_timeout(&(sw_pwm->sw_timer));
}

uint8_t sw_pwm_check_timeout(SW_PWM_STRUCT* sw_pwm)
{
    return sw_timer_check_timeout(&(sw_pwm->sw_timer));
}

void sw_pwm_tick_handler(SW_PWM_STRUCT* sw_pwm, uint16_t ticks)
{
    uint16_t counter;
    if(sw_timer_check_enable(&(sw_pwm->sw_timer))){
        counter = sw_timer_get_counter(&(sw_pwm->sw_timer));
/**********************************************/
        if((counter >= sw_pwm->compare_1)
        &&(counter < sw_pwm->compare_2)){
            if(sw_pwm->state.idle_level){
                if(sw_pwm->set_low_callback){
                    sw_pwm->set_low_callback();
                }
            }
            else{
                if(sw_pwm->set_high_callback){
                    sw_pwm->set_high_callback();
                }
            }
        }
        if(counter >= sw_pwm->compare_2){
            if(sw_pwm->state.idle_level){
                if(sw_pwm->set_high_callback){
                    sw_pwm->set_high_callback();
                }
            }
            else{
                if(sw_pwm->set_low_callback){
                    sw_pwm->set_low_callback();
                }
            }
        }
        if(counter == sw_pwm->compare_1){
            if(sw_pwm->compare_1_callback){
                sw_pwm->compare_1_callback();
            }
        }
        if(counter == sw_pwm->compare_2){
            if(sw_pwm->compare_2_callback){
                sw_pwm->compare_2_callback();
            }
        }
/**********************************************/
/**********************************************
		if((counter ==sw_pwm->compare_1)||(counter ==sw_pwm->compare_1)){
			sw_pwm->state.current_level = !sw_pwm->state.current_level;
			if(sw_pwm->state.current_level){
				if(sw_pwm->set_high_callback){
					sw_pwm->set_high_callback();
				}
			}
			else{
				if(sw_pwm->set_low_callback){
					sw_pwm->set_low_callback();
				}
			}
		}
        if(counter ==sw_pwm->compare_1){
            if(sw_pwm->compare_1_callback){
                sw_pwm->compare_1_callback();
            }
        }
        if(counter == sw_pwm->compare_2){
            if(sw_pwm->compare_2_callback){
                sw_pwm->compare_2_callback();
            }
        }
**********************************************/
        sw_timer_tick_handler(&(sw_pwm->sw_timer), ticks);
    }
}

void sw_pwm_init(SW_PWM_STRUCT* sw_pwm, uint16_t period, uint16_t compare_1, uint16_t compare_2, uint8_t idle_level,
					void (*period_timeout_callback_handler)(void* p),
					void (*set_high_callback_handler)(void),
					void (*set_low_callback_handler)(void),
					void (*compare_1_callback_handler)(void),
					void (*compare_2_callback_handler)(void))
{
	sw_timer_init(&(sw_pwm->sw_timer), period,
					(SW_TIMER_STRUCT*)period_timeout_callback_handler);
	sw_pwm->compare_1 = compare_1;
	sw_pwm->compare_2 = compare_2;
	sw_pwm->set_high_callback = set_high_callback_handler;
	sw_pwm->set_low_callback = set_low_callback_handler;
	sw_pwm->compare_1_callback = compare_1_callback_handler;
	sw_pwm->compare_2_callback = compare_2_callback_handler;
	sw_pwm->state.idle_level = idle_level;
}


void sw_pwm_group_tick_handler(SW_PWM_GROUP_STRUCT* sw_pwm_group, uint16_t ticks)
{
    static uint8_t i;
    if(ticks > 0){
        for (i = 0; i < sw_pwm_group->sw_pwm_num; i++) {
            sw_pwm_tick_handler(&(sw_pwm_group->sw_pwm[i]), ticks);
        }
    }
}

void sw_pwm_group_init(SW_PWM_GROUP_STRUCT* sw_pwm_group,
                               uint8_t sw_pwm_group_sw_pwm_num,
                               SW_PWM_STRUCT* sw_pwm_group_space)
{
	memset(sw_pwm_group_space, 0, sizeof(SW_PWM_STRUCT)*sw_pwm_group_sw_pwm_num);
    sw_pwm_group->sw_pwm_pointer = 0;
    sw_pwm_group->sw_pwm_num = sw_pwm_group_sw_pwm_num;
}

SW_PWM_STRUCT* sw_pwm_new(SW_PWM_GROUP_STRUCT* sw_pwm_group,
                                uint16_t period, uint8_t compare_1, uint8_t compare_2, uint8_t idle_level,
                                void (*period_timeout_callback_handler)(void* p),
                                void (*set_high_callback_handler)(void),
                                void (*set_low_callback_handler)(void),
                                void (*compare_1_callback_handler)(void),
                                void (*compare_2_callback_handler)(void))
{
    SW_PWM_STRUCT* sw_pwm;
   if(sw_pwm_group->sw_pwm_pointer < sw_pwm_group->sw_pwm_num){
//        sw_pwm = &(sw_pwm[sw_pwm_group->sw_pwm_pointer]);
		sw_pwm = sw_pwm_group->sw_pwm + sw_pwm_group->sw_pwm_pointer;
        sw_pwm_group->sw_pwm_pointer++;
		sw_pwm_init(sw_pwm, period, compare_1, compare_2, idle_level,
					period_timeout_callback_handler,
					set_high_callback_handler,
					set_low_callback_handler,
					compare_1_callback_handler,
					compare_2_callback_handler);
        return sw_pwm;
    }
    else{
        return 0;
    }
}

